using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace AuthService.Infrastructure.Monitoring;

/// <summary>
/// 指标收集后台服务
/// 定期收集和记录系统指标
/// </summary>
public class MetricsCollectionService : BackgroundService
{
    private readonly IMetricsCollector _metricsCollector;
    private readonly ILogger<MetricsCollectionService> _logger;
    private readonly TimeSpan _collectionInterval = TimeSpan.FromMinutes(1);

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="metricsCollector">指标收集器</param>
    /// <param name="logger">日志记录器</param>
    public MetricsCollectionService(IMetricsCollector metricsCollector, ILogger<MetricsCollectionService> logger)
    {
        _metricsCollector = metricsCollector;
        _logger = logger;
    }

    /// <summary>
    /// 执行后台任务
    /// </summary>
    /// <param name="stoppingToken">停止令牌</param>
    /// <returns>任务</returns>
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("指标收集服务已启动");

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                await CollectSystemMetricsAsync();
                await Task.Delay(_collectionInterval, stoppingToken);
            }
            catch (OperationCanceledException)
            {
                // 正常停止
                break;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "收集系统指标时发生异常");
                await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
            }
        }

        _logger.LogInformation("指标收集服务已停止");
    }

    /// <summary>
    /// 收集系统指标
    /// </summary>
    /// <returns>任务</returns>
    private async Task CollectSystemMetricsAsync()
    {
        try
        {
            // 收集内存使用情况
            var memoryUsage = GC.GetTotalMemory(false);
            _metricsCollector.SetGauge("system_memory_usage_bytes", memoryUsage);
            _metricsCollector.SetGauge("system_memory_usage_mb", memoryUsage / 1024.0 / 1024.0);

            // 收集GC信息
            for (int generation = 0; generation <= 2; generation++)
            {
                var collections = GC.CollectionCount(generation);
                _metricsCollector.SetGauge("system_gc_collections", collections, new Dictionary<string, string>
                {
                    ["generation"] = generation.ToString()
                });
            }

            // 收集线程池信息
            ThreadPool.GetAvailableThreads(out var availableWorkerThreads, out var availableCompletionPortThreads);
            ThreadPool.GetMaxThreads(out var maxWorkerThreads, out var maxCompletionPortThreads);

            _metricsCollector.SetGauge("system_threadpool_available_worker_threads", availableWorkerThreads);
            _metricsCollector.SetGauge("system_threadpool_available_completion_port_threads", availableCompletionPortThreads);
            _metricsCollector.SetGauge("system_threadpool_max_worker_threads", maxWorkerThreads);
            _metricsCollector.SetGauge("system_threadpool_max_completion_port_threads", maxCompletionPortThreads);

            // 收集运行时间
            var uptime = Environment.TickCount64;
            _metricsCollector.SetGauge("system_uptime_milliseconds", uptime);
            _metricsCollector.SetGauge("system_uptime_seconds", uptime / 1000.0);

            // 收集进程信息
            using var process = System.Diagnostics.Process.GetCurrentProcess();
            _metricsCollector.SetGauge("system_process_working_set_bytes", process.WorkingSet64);
            _metricsCollector.SetGauge("system_process_private_memory_bytes", process.PrivateMemorySize64);
            _metricsCollector.SetGauge("system_process_virtual_memory_bytes", process.VirtualMemorySize64);
            _metricsCollector.SetGauge("system_process_threads", process.Threads.Count);

            // 收集CPU使用率（简化版本）
            var cpuTime = process.TotalProcessorTime;
            _metricsCollector.SetGauge("system_process_cpu_time_seconds", cpuTime.TotalSeconds);

            _logger.LogDebug("系统指标收集完成");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "收集系统指标失败");
        }
    }
}
